﻿using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace XYS.Core.Util;

public static partial class Extention
{
    /// <summary>
    /// 删除文件
    /// </summary>
    /// <param name="filePath"></param>
    /// <returns>是否删除成功</returns>
    public static bool DeleteFile(this string filePath)
    {
        if (!File.Exists(filePath)) return false;

        try { File.Delete(filePath); } catch { return false; }

        return true;
    }

    /// <summary>
    /// 删除文件夹
    /// </summary>
    /// <param name="dirPath"></param>
    /// <returns>是否删除成功</returns>
    public static bool DeleteDir(this string dirPath)
    {
        if (!Directory.Exists(dirPath)) return false;
        try { Directory.Delete(dirPath, true); } catch { return false; }
        return true;
    }

    /// <summary>
    /// 删除开头指定字符串
    /// </summary>
    /// <param name="str"></param>
    /// <param name="trimString"></param>
    /// <returns></returns>
    public static string TrimStart(this string str, string trimString)
    {
        if (str.StartsWith(trimString)) return str.Substring(trimString.Length);
        return str;
    }


    /// <summary>
    /// 判断指定的字符串是null、空还是仅由空白字符组成。
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string str) => string.IsNullOrWhiteSpace(str);
    /// <summary>
    /// 判断指定的字符串是null还是空字符串。
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsNullOrEmpty([NotNullWhen(false)] this string str) => string.IsNullOrEmpty(str);

    /// <summary>
    /// 转为字节数组
    /// </summary>
    /// <param name="base64Str">base64字符串</param>
    /// <returns></returns>
    public static byte[] ToBytes_FromBase64Str(this string base64Str)
    {
        return Convert.FromBase64String(base64Str);
    }
    /// <summary>
    /// URL 编码
    /// </summary>
    /// <param name="originalString"></param>
    /// <returns></returns>
    public static string UrlEncode(this string originalString)
    {
        return HttpUtility.UrlEncode(originalString)?.Replace("+", "%20");
    }

    /// <summary>
    /// URL 解码
    /// </summary>
    /// <param name="encodedString"></param>
    /// <returns></returns>
    public static string UrlDecode(this string encodedString)
    {
        return HttpUtility.UrlDecode(encodedString);
    }

    /// <summary>
    /// 转换为MD5摘要后的字符串（默认为32位）
    /// </summary>
    /// <param name="str"></param>
    /// <param name="key">盐</param>
    /// <returns></returns>
    public static string ToMD5String(this string str, string key = "xysaxssbb")
    {
        string str1 = str + key;
        MD5 md5 = MD5.Create();
        byte[] inputBytes = Encoding.UTF8.GetBytes(str1);
        byte[] hashBytes = md5.ComputeHash(inputBytes);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hashBytes.Length; i++)
        {
            sb.Append(hashBytes[i].ToString("x2"));
        }
        md5.Dispose();

        return sb.ToString();
    }

    /// <summary>
    /// Base64 编码
    /// 注:默认采用UTF8编码
    /// </summary>
    /// <param name="source">待编码的明文</param>
    /// <returns>编码后的字符串</returns>
    public static string Base64Encode(this string source)
    {
        return Base64Encode(source, Encoding.UTF8);
    }

    /// <summary>
    /// Base64 编码
    /// </summary>
    /// <param name="source">待编码的明文</param>
    /// <param name="encoding">编码采用的编码方式</param>
    /// <returns></returns>
    public static string Base64Encode(this string source, Encoding encoding)
    {
        string encode = string.Empty;
        byte[] bytes = encoding.GetBytes(source);
        try
        {
            encode = Convert.ToBase64String(bytes);
        }
        catch
        {
            encode = source;
        }
        return encode;
    }

    /// <summary>
    /// Base64 解码
    /// 注:默认使用UTF8编码
    /// </summary>
    /// <param name="result">待解码的密文</param>
    /// <returns>解码后的字符串</returns>
    public static string Base64Decode(this string result)
    {
        return Base64Decode(result, Encoding.UTF8);
    }

    /// <summary>
    /// Base64 解码
    /// </summary>
    /// <param name="result">待解码的密文</param>
    /// <param name="encoding">解码采用的编码方式，注意和编码时采用的方式一致</param>
    /// <returns>解码后的字符串</returns>
    public static string Base64Decode(this string result, Encoding encoding)
    {
        try { return encoding.GetString(Convert.FromBase64String(result)); }
        catch { return result; }
    }

    /// <summary>
    /// 计算SHA1摘要
    /// 注：默认使用UTF8编码
    /// </summary>
    /// <param name="str">字符串</param>
    /// <returns></returns>
    public static byte[] ToSHA1Bytes(this string str)
    {
        return str.ToSHA1Bytes(Encoding.UTF8);
    }

    /// <summary>
    /// 计算SHA1摘要
    /// </summary>
    /// <param name="str">字符串</param>
    /// <param name="encoding">编码</param>
    /// <returns></returns>
    public static byte[] ToSHA1Bytes(this string str, Encoding encoding)
    {
        SHA1 sha1 = SHA1.Create();
        byte[] inputBytes = encoding.GetBytes(str);
        byte[] outputBytes = sha1.ComputeHash(inputBytes);

        return outputBytes;
    }

    /// <summary>
    /// string转int
    /// </summary>
    /// <param name="str">字符串</param>
    /// <returns></returns>
    public static int ToInt(this string str)
    {
        str = str?.Replace("\0", "");
        if (string.IsNullOrEmpty(str))
            return 0;
        return Convert.ToInt32(str);
    }

    /// <summary>
    /// 转换为日期格式
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static DateTime? ToDateTime(this string str)
    {
        return DateTime.TryParse(str, out DateTime dt) ? dt : null;
    }

    /// <summary>
    /// 缩写字符串
    /// </summary>
    /// <param name="text">原字符串</param>
    /// <param name="length">最大长度</param>
    /// <param name="last">超过最大长度后的缩写</param>
    /// <returns></returns>
    public static string Abbreviation(this string text, int length, string last = "...")
    {
        if (text.Length > length) text = string.Concat(text.AsSpan(0, length), last);
        return text;
    }

    /// <summary>
    /// 转为流量字符串
    /// </summary>
    /// <param name="bytes">流量大小</param>
    /// <returns></returns>
    public static string ToTrafficString(this long bytes)
    {
        if (bytes > 0)
        {
            if (bytes < 1000) return bytes.ToString() + "B";
            if (bytes < 1000 * 1024) return (bytes / 1024D).ToString("#.##") + "KB";
            if (bytes < 1000 * 1024 * 1024) return (bytes / 1024D / 1024D).ToString("#.##") + "MB";
            if (bytes < 1000D * 1024 * 1024 * 1024) return (bytes / 1024D / 1024D / 1024D).ToString("#.##") + "GB";
            else return (bytes / 1024D / 1024D / 1024D / 1024D).ToString("#.##") + "TB";
        }
        else
        {
            if (bytes > -1000) return bytes.ToString() + "B";
            if (bytes > -1000 * 1024) return (bytes / 1024D).ToString("#.##") + "KB";
            if (bytes > -1000 * 1024 * 1024) return (bytes / 1024D / 1024D).ToString("#.##") + "MB";
            if (bytes > -1000D * 1024 * 1024 * 1024) return (bytes / 1024D / 1024D / 1024D).ToString("#.##") + "GB";
            else return (bytes / 1024D / 1024D / 1024D / 1024D).ToString("#.##") + "TB";
        }
    }

    /// <summary>
    /// 去除原字符串结尾处的所有替换字符串
    /// 如：原字符串"sdlfjdcdcd",替换字符串"cd" 返回"sdlfjd"
    /// </summary>
    /// <param name="strSrc">源字符串</param>
    /// <param name="strTrim">去除的字符串</param>
    /// <param name="isLoop">是否循环去除,默认为true</param>
    /// <returns></returns>
    public static string TrimEnd(this string strSrc, string strTrim, bool isLoop = true)
    {
        if (string.IsNullOrEmpty(strSrc) || string.IsNullOrEmpty(strTrim)) return strSrc;
        if (strSrc.EndsWith(strTrim))
        {
            string strDes = strSrc[..^strTrim.Length];
            return !isLoop ? strDes : strDes.TrimEnd(strTrim);
        }
        return strSrc;
    }

    /// <summary>
    /// 删除字符串内的空格和回车
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static string RemoveAndEnter(this string str)
    {
        return str?.Replace("\r", "").Replace("\n", "").Replace(" ", "");
    }

    /// <summary>
    /// 返回该字符串是否手机号
    /// </summary>
    /// <param name="str">源字符串</param>
    /// <returns></returns>
    public static bool IsHandset(this string str)
    {
        return Regex.IsMatch(str, @"^1[3456789]\d{9}$");
    }


    /// <summary>
    /// 不允许作为文件名的特殊字符
    /// </summary>
    public static readonly List<char> SpecialSymbols = new() { '\\', '/', ':', '*', '?', '"', '<', '>', '|' };

    /// <summary>
    /// 替换文件名中不允许出现的特殊字符
    /// </summary>
    /// <param name="str"></param>
    /// <param name="replaceType">替换类型（1：使用相似字符替换，2：直接去除特殊字符，3：使用“-”替换）</param>
    /// <returns></returns>
    public static string ReplaceFileNameSpecialSymbol(this string str, int replaceType = 1)
    {
        if (string.IsNullOrWhiteSpace(str)) return str;

        StringBuilder result = new(str);

        foreach (char specialSymbol in SpecialSymbols)
        {
            switch (replaceType)
            {
                case 1:
                    result.Replace(specialSymbol, GetSimilarCharacter(specialSymbol));
                    break;
                case 2:
                    result.Replace(specialSymbol.ToString(), string.Empty);
                    break;
                case 3:
                    result.Replace(specialSymbol, '-');
                    break;
                default:
                    throw new ArgumentException("Invalid replaceType. Use 1, 2, or 3.");
            }
        }

        return result.ToString();
    }

    /// <summary>
    /// 获取一个相似字符
    /// </summary>
    /// <param name="original"></param>
    /// <returns></returns>
    private static char GetSimilarCharacter(char original)
    {
        return original switch
        {
            '\\' => '＼',
            '/' => '／',
            ':' => '：',
            '*' => '＊',
            '?' => '？',
            '"' => '“',
            '<' => '＜',
            '>' => '＞',
            '|' => '｜',
            _ => original
        };
    }


    /// <summary>
    /// Unicode 解码
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static string DecodeUnicodeString(this string input)
    {
        if (input.IsNullOrWhiteSpace()) return input;
        return Regex.Unescape(input);
    }


}